package com.base.controller.czb.czbapi;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.base.comm.CommUrls;
import com.base.controller.utils.CZB.CZBPayUtils;
import com.base.helper.VosHelper;
import com.base.po.czb_sdk.GasOrder;
import com.base.po.param.NetState;
import com.base.po.voip.Subscribers;
import com.base.po.voip.Users;
import com.base.po.voip.UsersConfig;
import com.base.po.wx.MyConfig;
import com.base.po.wx.WXPay;
import com.base.po.wx.WXPayConfig;
import com.base.po.wx.WXPayUtil;
import com.base.service.CZB.GasOrderService;
import com.base.service.SubscribersService;
import com.base.service.UsersConfigService;
import com.base.service.UsersService;
import com.base.utils.IP;
import com.base.utils.PayCommonUtil;
import com.base.utils.Produce;
import com.base.utils.StringUtil;
import org.jdom.JDOMException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.util.*;

/**
 * 支付
 *
 * @author K
 */
@Controller
@RequestMapping("/gas")
public class GasOrderPayController {

    // 用户信息
    @Autowired
    UsersService usersService;
    @Autowired
    SubscribersService subscribersService;
    @Autowired
    UsersConfigService usersConfigService;
    @Autowired
    GasOrderService gasOrderService;


    // 支付宝公用变量
    private String serverUrl = "https://openapi.alipay.com/gateway.do"; // 支付宝网关 固定
    private String FORMAT = "json"; // 参数返回格式 固定
    private String CHARSET = "UTF-8"; // 编码集 固定
    private String SIGN_TYPE = "RSA2"; // 签名算法类型 固定
    private String ALIPAY_PUBLIC_KEY; // 支付宝公钥
    private String APP_ID; // appid
    private String APP_PRIVATE_KEY; // 商户私钥

    // 随机字符串
    private String randomString = PayCommonUtil.getRandomString(32);

    // 微信公用变量
    private String appid; // appid
    private String mch_id; // 商户id
    private String API_KEY; // 商户密钥

    //生成订单
    @RequestMapping(value = "/payOrder", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
        public NetState insertOrder(HttpServletRequest meRequest,String parentId, String orderId, String openId, Integer type) {
        NetState netState = new NetState();

        Users users = usersService.selectByPrimaryKey(parentId);
        UsersConfig config = usersConfigService.selectByParentId(parentId);
        GasOrder gasOrder = gasOrderService.selectByPrimaryKey(orderId);
        if (users  == null || gasOrder == null) {
            netState.setErrorCode(NetState.NODATA);
            netState.setData("参数异常或信息不存在");
            return netState;
        }

        // 进入支付环节
        switch (type) {
            // 支付宝
            case 1:
                // 支付
                this.APP_ID = users.getAppid(); // APPID
                this.APP_PRIVATE_KEY = users.getKeypath(); // 商户私钥
                this.ALIPAY_PUBLIC_KEY = users.getAlipubkey(); // 支付宝公钥
                // 未开通支付宝接口 则失败
                if (APP_ID == null || APP_PRIVATE_KEY == null || ALIPAY_PUBLIC_KEY == null || APP_ID.isEmpty()
                        || APP_PRIVATE_KEY.isEmpty() || ALIPAY_PUBLIC_KEY.isEmpty()) {
                    netState.setErrorCode(NetState.API_NOT_PER);
                    netState.setData("应用状态异常，商户未配置在线支付信息");
                    return netState;
                }
                // 获得初始化的AlipayClient
                AlipayClient alipayClient = new DefaultAlipayClient(serverUrl, APP_ID, APP_PRIVATE_KEY, FORMAT, CHARSET,
                        ALIPAY_PUBLIC_KEY, SIGN_TYPE);
                // 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
                AlipayTradeAppPayRequest aliRequest = new AlipayTradeAppPayRequest();
                // 初始化支付宝信息参数
                AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
                model.setTotalAmount(gasOrder.getSbdpayamount().toString()); // 订单支付金额
                model.setOutTradeNo(gasOrder.getId()); // 商户网站唯一订单号
                model.setBody(gasOrder.getGasname() + "油费支付"); // 描述信息
                model.setSubject("油费支付"); // 订单标题
                model.setTimeoutExpress("90m"); // 最晚付款时间 后台固定
                model.setProductCode("QUICK_MSECURITY_PAY"); // 销售产品码 后台固定
                model.setGoodsType("1"); // 商品主类型:0-虚拟类商品 1-实物类商品 后台固定
                // 传入参数
                aliRequest.setBizModel(model);
                // 异步通知
                aliRequest.setNotifyUrl(CommUrls.THISSERVER + "gas/gasAliNotify");

                try {
                    // 这里和普通的接口调用不同，使用的是sdkExecute
                    AlipayTradeAppPayResponse response = alipayClient.sdkExecute(aliRequest);

                    gasOrder.setPaystatus(1);
                    gasOrderService.updateByPrimaryKeySelective(gasOrder);
                    netState.setErrorCode(NetState.SUCCESS_CONN);
                    netState.setData("调用支付宝成功");
                    netState.setJson(response.getBody()); // 写入JSON
                } catch (AlipayApiException e) {
                    e.printStackTrace();
                    // 调用失败
                    netState.setErrorCode(NetState.SIGN_ERROR);
                    netState.setData("非法操作");
                }
                break;
            // 微信
            case 2:
                // 支付
                this.appid = users.getWxappid(); // APPID
                this.mch_id = users.getWxmchid(); // 商户ID
                this.API_KEY = users.getWxapikey(); // 密钥
                // 未开通微信接口 则失败
                if (appid == null || mch_id == null || API_KEY == null || appid.isEmpty() || mch_id.isEmpty()
                        || API_KEY.isEmpty()) {
                    netState.setErrorCode(NetState.API_NOT_PER);
                    netState.setData("应用状态异常，商户未配置在线支付信息");
                    return netState;
                }

                // 一次签名 生成预付款信息
                SortedMap<String, Object> parameterMap = new TreeMap<String, Object>();
                parameterMap.put("appid", appid); // 应用appid
                parameterMap.put("mch_id", mch_id); // 商户号
                parameterMap.put("nonce_str", randomString); // 随机字符串
                parameterMap.put("body", gasOrder.getGasname() + "油费支付"); // 商品描述
                parameterMap.put("out_trade_no", gasOrder.getId()); // 商户订单号
                parameterMap.put("total_fee",
                        new DecimalFormat("0").format(gasOrder.getSbdpayamount().multiply(new BigDecimal(100)))); // 接口中参数支付金额单位为【分】，参数值不能带小数，所以乘以100
                parameterMap.put("spbill_create_ip", IP.getIpAddr(meRequest)); // 终端IP

                parameterMap.put("notify_url", CommUrls.THISSERVER + "gas/gasWxNotify"); // 通知地址
                parameterMap.put("trade_type", "APP"); // 交易类型
                String sign1 = PayCommonUtil.createSign("UTF-8", parameterMap, API_KEY); // 组装签名
                parameterMap.put("sign", sign1); // 签名
                String requestXML = PayCommonUtil.getRequestXml(parameterMap); // 组装XML
                String wxResult = PayCommonUtil.httpsRequest("https://api.mch.weixin.qq.com/pay/unifiedorder", "POST",
                        requestXML); // XML
                Map<String, String> map = null;
                try {
//                    map = PayCommonUtil.doXMLParse(wxResult);
                    map = WXPayUtil.xmlToMap(wxResult);
                } catch (JDOMException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }catch (Exception e){
                    e.printStackTrace();
                }

                if (map == null || map.get("prepay_id") == null || map.get("prepay_id").isEmpty()) {
                    netState.setErrorCode(NetState.PARAMS_ERROR);
                    netState.setData("交易状态异常，微信支付接口调取失败");
                    return netState;
                }

                try {
                    // 二次签名 返回App调用微信支付
                    SortedMap<String, Object> finalpackage = new TreeMap<String, Object>();
                    finalpackage.put("appid", appid); // 应用ID
                    finalpackage.put("partnerid", mch_id); // 商户号
                    Long time = (System.currentTimeMillis() / 1000);
                    finalpackage.put("timestamp", time.toString()); // 时间戳
                    finalpackage.put("noncestr", map.get("nonce_str")); // 随机字符串
                    finalpackage.put("prepayid", map.get("prepay_id")); // 预支付交易会话ID
                    finalpackage.put("package", "Sign=WXPay"); // 扩展字段
                    String sign2 = PayCommonUtil.createSign("UTF-8", finalpackage, API_KEY); // 组装签名
                    finalpackage.put("sign", sign2); // 签名

                    gasOrder.setPaystatus(1);
                    gasOrderService.updateByPrimaryKeySelective(gasOrder);
                    netState.setErrorCode(NetState.SUCCESS_CONN);
                    netState.setData("调用微信成功");
                    netState.setJson(finalpackage); // 写入JSON
                } catch (Exception e) {
                    e.printStackTrace();
                    netState.setErrorCode(NetState.PARAMS_ERROR);
                    netState.setData("交易状态异常，微信支付接口调取失败");
                }
                break;
            case 3:
                // 支付
                this.appid = config.getWxDevelopersAppid(); // 小程序APPID
                this.mch_id = users.getWxmchid(); // 商户ID
                this.API_KEY = users.getWxapikey(); // 小程序密钥
                // 未开通微信接口 则失败
                if (appid == null || mch_id == null || API_KEY == null || appid.isEmpty() || mch_id.isEmpty()
                        || API_KEY.isEmpty()) {
                    netState.setErrorCode(NetState.API_NOT_PER);
                    netState.setData("应用状态异常，商户未配置在线支付信息");
                    return netState;
                }

                // 一次签名 生成预付款信息
                SortedMap<String, Object> routineMap = new TreeMap<String, Object>();
                routineMap.put("appid", appid); // 应用appid
                routineMap.put("mch_id", mch_id); // 商户号
                routineMap.put("nonce_str", randomString); // 随机字符串
                routineMap.put("body", gasOrder.getGasname() + "油费支付"); // 商品描述
                routineMap.put("out_trade_no", gasOrder.getId()); // 商户订单号
                routineMap.put("total_fee",
                        new DecimalFormat("0").format(gasOrder.getSbdpayamount().multiply(new BigDecimal(100)))); // 接口中参数支付金额单位为【分】，参数值不能带小数，所以乘以100
                routineMap.put("spbill_create_ip", IP.getIpAddr(meRequest)); // 终端IP

                routineMap.put("notify_url", CommUrls.THISSERVER + "gas/gasWxRoutineNotify"); // 通知地址
                routineMap.put("trade_type", "JSAPI"); // 交易类型
                routineMap.put("openid", openId); // 小程序openId
                String routineSign1 = PayCommonUtil.createSign("UTF-8", routineMap, API_KEY); // 组装签名
                routineMap.put("sign", routineSign1); // 签名
                String routineXML = PayCommonUtil.getRequestXml(routineMap); // 组装XML
                String wxRoutineResult = PayCommonUtil.httpsRequest("https://api.mch.weixin.qq.com/pay/unifiedorder", "POST",
                        routineXML); // XML
                Map<String, String> wxRoutineMap = null;
                try {
//                    map = PayCommonUtil.doXMLParse(wxResult);
                    wxRoutineMap = WXPayUtil.xmlToMap(wxRoutineResult);
                } catch (JDOMException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }catch (Exception e){
                    e.printStackTrace();
                }

                if (wxRoutineMap == null || wxRoutineMap.get("prepay_id") == null || wxRoutineMap.get("prepay_id").isEmpty()) {
                    netState.setErrorCode(NetState.PARAMS_ERROR);
                    netState.setData("交易状态异常，微信支付接口调取失败");
                    return netState;
                }

                try {
                    // 二次签名 返回App调用微信支付
                    SortedMap<String, Object> routinePackage = new TreeMap<String, Object>();
                    Long time = (System.currentTimeMillis() / 1000);
                    routinePackage.put("appId", appid); // 应用ID
                    routinePackage.put("timeStamp", time.toString()); // 时间戳
                    routinePackage.put("nonceStr", wxRoutineMap.get("nonce_str")); // 随机字符串
                    routinePackage.put("package", "prepay_id=" + wxRoutineMap.get("prepay_id")); // 预支付交易会话ID
                    routinePackage.put("signType", "MD5"); // 随机字符串
                    String routineSign2 = PayCommonUtil.createSign("UTF-8", routinePackage, API_KEY); // 组装签名
                    routinePackage.put("sign", routineSign2); // 签名

                    gasOrder.setPaystatus(1);
                    gasOrderService.updateByPrimaryKeySelective(gasOrder);
                    netState.setErrorCode(NetState.SUCCESS_CONN);
                    netState.setData("调用微信成功");
                    netState.setJson(routinePackage); // 写入JSON
                } catch (Exception e) {
                    e.printStackTrace();
                    netState.setErrorCode(NetState.PARAMS_ERROR);
                    netState.setData("交易状态异常，微信支付接口调取失败");
                }
                break;
        }
        return netState;
    }

    /**
     * 支付宝异步返回结果
     *
     * @param request  获取支付宝返回的信息
     * @param response 返回给支付宝的信息
     */
    @RequestMapping(value = "/gasAliNotify", method = {RequestMethod.POST, RequestMethod.GET})
    public void gasAliNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 获取支付宝POST过来的反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = iter.next();
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++)
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            // 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8");
            params.put(name, valueStr);
        }
        // 在通知返回参数列表中，除去sign、sign_type两个参数外，凡是通知返回回来的参数皆是待验签的参数。
        boolean signVerified = AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, CHARSET, SIGN_TYPE);
        // 验证签名
        sign:
        if (signVerified) {
            // 验证支付状态
            if (params.get("trade_status").equals("TRADE_SUCCESS")) {
                // 订单信息
                GasOrder gasOrder = gasOrderService.selectByPrimaryKey(params.get("out_trade_no"));
                // 判断该订单是否存在
                if (gasOrder == null) {
                    break sign;
                }

                String callBackResult = CZBPayUtils.getPayCallBack(Produce.getNowDate().getTime(), gasOrder.getCzborderid(),
                        gasOrder.getCzbpayamount().multiply(new BigDecimal(100)).intValue(), 200);
                System.out.println("callbackResult"+callBackResult);
                if (callBackResult.trim().equals("200")){
                    gasOrder.setPaystatus(2);
                    gasOrder.setPaymethod("支付宝");
                    gasOrderService.updateByPrimaryKeySelective(gasOrder);

                    // 扣除话费
                    Subscribers user = subscribersService.selectByPrimaryKey(gasOrder.getUserid());
                    Users agent = usersService.selectByPrimaryKey(user.getParentid());
                    BigDecimal money = gasOrder.getAmountgun().subtract(gasOrder.getSbdpayamount()).setScale(2, BigDecimal.ROUND_HALF_UP);
                    BigDecimal sbdFree = money.multiply(new BigDecimal(-1)); // 需要扣除的费用
                    VosHelper.PayVosAccount("{\"ownerName\":\"" + agent.getAgentprefix() + user.getMobile()
                            + "\",\"ownerType\":\"2\",\"money\":\"" + sbdFree + "\",\"memo\":\"" + user.getUsername()
                            + "，加油抵扣" + sbdFree + "元\"}");
                }else {
                    break sign;
                }
            }
            // 返回success
            response.getWriter().print("success"); // 固定 不可删除
        } else {
            // 返回fail
            response.getWriter().print("fail"); // 固定 不可删除
        }
    }

    /**
     * 微信异步返回结果
     *
     * @param request  获取支付宝返回的信息
     * @param response 返回给支付宝的信息
     */
    @RequestMapping(value = "/gasWxNotify", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public String gasWxNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        InputStream inStream = request.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        String notifyData = new String(outSteam.toByteArray(), StandardCharsets.UTF_8); // 支付结果通知的xml格式数据
        outSteam.close();
        inStream.close();
        // 微信提供的验签
        WXPayConfig config = new MyConfig(appid, mch_id, API_KEY); // 配置信息
        WXPay wxpay = new WXPay(config);
        Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData); // 转换成map
        Map<String, String> return_data = new HashMap<String, String>(); // 返回
        boolean wxSign = wxpay.isPayResultNotifySignatureValid(notifyMap);
        if (notifyMap.get("trade_type").equals("MWEB")){
            wxSign = true;
        }
        // 验证签名
        sign:
        if (wxSign) {
            // 验证支付状态
            if (notifyMap.get("result_code").equals("SUCCESS")) {
                // 继续商户自身业务处理
                GasOrder gasOrder = gasOrderService.selectByPrimaryKey(notifyMap.get("out_trade_no"));
                // 判断该订单是否存在
                if (gasOrder == null) {
                    break sign;
                }

                String callBackResult = CZBPayUtils.getPayCallBack(Produce.getNowDate().getTime(), gasOrder.getCzborderid(),
                        gasOrder.getCzbpayamount().multiply(new BigDecimal(100)).intValue(), 200);
                System.out.println("微信支付回告:"+callBackResult);
                if (callBackResult.trim().equals("200")){
                    gasOrder.setPaystatus(2);
                    gasOrder.setPaymethod("微信");
                    gasOrderService.updateByPrimaryKeySelective(gasOrder);

                    // 扣除话费
                    Subscribers user = subscribersService.selectByPrimaryKey(gasOrder.getUserid());
                    Users agent = usersService.selectByPrimaryKey(user.getParentid());
                    BigDecimal money = gasOrder.getAmountgun().subtract(gasOrder.getSbdpayamount()).setScale(2, BigDecimal.ROUND_HALF_UP);
                    BigDecimal sbdFree = money.multiply(new BigDecimal(-1));
                    VosHelper.PayVosAccount("{\"ownerName\":\"" + agent.getAgentprefix() + user.getMobile()
                            + "\",\"ownerType\":\"2\",\"money\":\"" + sbdFree + "\",\"memo\":\"" + user.getUsername()
                            + "，加油抵扣" + sbdFree + "元\"}");
                }else {
                    break sign;
                }
            }
            // 返回SUCCESS
            return_data.put("return_code", "SUCCESS"); // 固定 不可删除
            return_data.put("return_msg", "OK");
        } else {
            // 签名错误，如果数据里没有sign字段，也认为是签名错误
            // 返回FAIL
            return_data.put("return_code", "FAIL"); // 固定 不可删除
            return_data.put("return_msg", "return_code不正确");
        }
        return StringUtil.GetMapToXML(return_data);
    }

    /**
     * 微信异步返回结果
     *
     * @param request  获取支付宝返回的信息
     * @param response 返回给支付宝的信息
     */
    @RequestMapping(value = "/gasWxRoutineNotify", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public String gasWxRoutineNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        InputStream inStream = request.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        String notifyData = new String(outSteam.toByteArray(), StandardCharsets.UTF_8); // 支付结果通知的xml格式数据
        outSteam.close();
        inStream.close();
        // 微信提供的验签
        WXPayConfig config = new MyConfig(appid, mch_id, API_KEY); // 配置信息
        WXPay wxpay = new WXPay(config);
        Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData); // 转换成map
        Map<String, String> return_data = new HashMap<String, String>(); // 返回
        boolean wxSign = wxpay.isPayResultNotifySignatureValid(notifyMap);
        if (notifyMap.get("trade_type").equals("MWEB")){
            wxSign = true;
        }
        // 验证签名
        sign:
        if (wxSign) {
            // 验证支付状态
            if (notifyMap.get("result_code").equals("SUCCESS")) {
                // 继续商户自身业务处理
                GasOrder gasOrder = gasOrderService.selectByPrimaryKey(notifyMap.get("out_trade_no"));
                // 判断该订单是否存在
                if (gasOrder == null) {
                    break sign;
                }

                String callBackResult = CZBPayUtils.getPayCallBack(Produce.getNowDate().getTime(), gasOrder.getCzborderid(),
                        gasOrder.getCzbpayamount().multiply(new BigDecimal(100)).intValue(), 200);
                System.out.println("小程序支付回告:"+callBackResult);
                if (callBackResult.trim().equals("200")){
                    gasOrder.setPaystatus(2);
                    gasOrder.setPaymethod("微信小程序");
                    gasOrderService.updateByPrimaryKeySelective(gasOrder);

                    // 扣除话费
                    Subscribers user = subscribersService.selectByPrimaryKey(gasOrder.getUserid());
                    Users agent = usersService.selectByPrimaryKey(user.getParentid());
                    BigDecimal money = gasOrder.getAmountgun().subtract(gasOrder.getSbdpayamount()).setScale(2, BigDecimal.ROUND_HALF_UP);
                    BigDecimal sbdFree = money.multiply(new BigDecimal(-1));
                    VosHelper.PayVosAccount("{\"ownerName\":\"" + agent.getAgentprefix() + user.getMobile()
                            + "\",\"ownerType\":\"2\",\"money\":\"" + sbdFree + "\",\"memo\":\"" + user.getUsername()
                            + "，加油抵扣" + sbdFree + "元\"}");
                }else {
                    break sign;
                }
            }
            // 返回SUCCESS
            return_data.put("return_code", "SUCCESS"); // 固定 不可删除
            return_data.put("return_msg", "OK");
        } else {
            // 签名错误，如果数据里没有sign字段，也认为是签名错误
            // 返回FAIL
            return_data.put("return_code", "FAIL"); // 固定 不可删除
            return_data.put("return_msg", "return_code不正确");
        }
        return StringUtil.GetMapToXML(return_data);
    }
}
